use super::*;

/// An [Anchor Point Table](
/// https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6ankr.html).
/// The anchor point table (tag name: 'ankr') provides a way to define anchor points—points within the coordinate space of a given glyph independent of the control points used to render the glyph. Anchor points are used in conjunction with the 'kerx'.
#[derive(Clone)]
pub struct Table<'a> {
	// UInt16	version	Version number (set to zero)
	pub version: u16,
	// UInt16	flags	Flags (currently unused; set to zero)
	pub flags: u16,
	lookup: aat::Lookup<'a>,
	// Ideally, Glyphs Data can be represented as an array,
	// but Apple's spec doesn't specify that Glyphs Data members have padding or not.
	// Meaning we cannot simply iterate over them.
	glyphs_data: &'a [u8],
}
impl<'a> Table<'a> {
	/// Parses a table from raw data.
	///
	/// `num_glyphs` is from the `maxp` table.
	pub fn parse(num_glyphs: u16, data: &'a [u8]) -> Option<Self> {
		let mut s = Stream::new(data);
		let version: u16 = s.read()?;
		if version != 0 {
			return None;
		}
		let flags: u16 = s.read()?; // reserved

		// TODO: we should probably check that offset is larger than the header size (8)
		let lookup_table = s.read_at_offset32(data)?;
		let glyphs_data = s.read_at_offset32(data)?;
		Some(Table {
			version,
			flags,
			lookup: aat::Lookup::parse(num_glyphs, lookup_table)?,
			glyphs_data,
		})
	}
	/// Returns a list of anchor points for the specified glyph.
	pub fn points(&self, glyph_id: GlyphId) -> Option<LazyArray32<'a, Point>> {
		let offset = self.lookup.get(glyph_id)?;

		let mut s = Stream::new_at(self.glyphs_data, usize::from(offset))?;
		let number_of_points = s.read::<u32>()?;
		s.read_array32::<Point>(number_of_points)
	}
}
impl core::fmt::Debug for Table<'_> {
	fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
		write!(f, "Table {{ ... }}")
	}
}

/// An anchor point.
#[allow(missing_docs)]
#[derive(Clone, Copy, PartialEq, Eq, Default, Debug)]
pub struct Point {
	pub x: i16,
	pub y: i16,
}
impl FromData for Point {
	const SIZE: usize = 4;
	#[inline]
	fn parse(data: &[u8]) -> Option<Self> {
		let mut s = Stream::new(data);
		Some(Point {
			x: s.read::<i16>()?,
			y: s.read::<i16>()?,
		})
	}
}
